/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年6月5日
 */
package com.massyframework.beanskin.runtime.framework.installing.assembly;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.massyframework.beanskin.ModuleException;
import com.massyframework.beanskin.ModuleIdentifier;
import com.massyframework.beanskin.ModuleRepository;
import com.massyframework.beanskin.ModuleRuntimeException;
import com.massyframework.beanskin.assembly.Assembly;
import com.massyframework.beanskin.assembly.AssemblyBuilder;
import com.massyframework.beanskin.runtime.ModuleRegistry;
import com.massyframework.beanskin.runtime.framework.installing.ModuleScanner;
import com.massyframework.beanskin.service.ServiceRepositoryFactory;
import com.massyframework.beanskin.util.exceptioncollect.ExceptionCollectUtils;
import com.massyframework.beanskin.util.localstore.LocalStore;

/**
 * 装配件安装器
 * @author huangkh
 *
 */
public class AssemblyInstaller {
	
	private Logger logger = LoggerFactory.getLogger(AssemblyInstaller.class);

	/**
	 * 
	 */
	public AssemblyInstaller() {
		
	}

	/**
	 * 加载并安装
	 * @param kernel {@link Assembly},装配件
	 * @param localStore {@link LocalStore},本地存储
	 * @param moduleRepository {@link ModuleRepository}, 模块资源库
	 * @param executor {@link ExecutorService}, 执行服务线程池
	 */
	public void installAssemblies(Assembly kernel, LocalStore localStore, 
			ModuleRepository moduleRepository, ServiceRepositoryFactory factory, ExecutorService executor) {
		Path[] roots = this.getRoots(localStore);
		Map<ModuleIdentifier, AssemblyBuilder> assemblyMap = this.loadAssemblies(kernel, roots, localStore, moduleRepository);
		
		ModuleRegistry registry =(ModuleRegistry)moduleRepository;
		for (AssemblyBuilder builder: assemblyMap.values()) {
			executor.execute(()->{
				try {
					builder.serviceRepositoryFactory(factory);
					Assembly assembly = builder.build();
					registry.register(assembly);
				}catch(ModuleException e) {
					
				}catch(Exception e) {
					ModuleRuntimeException newException = 
							new ModuleRuntimeException(builder.getModuleIdentifier(), e);
					ExceptionCollectUtils.addException(newException);
					
					
					if (logger.isErrorEnabled()) {
						logger.error(e.getMessage(), e);
					}
				}
			});
		}
	}
	
	/**
	 * 加载插件
	 * @param kernel {@link Assembly},内核装配件
	 * @param roots {@link Paths}数组
	 * @param moduleRepository {@link ModuleRepository},模块资源库
	 * @return {@link Map}
	 */
	protected Map<ModuleIdentifier, AssemblyBuilder> loadAssemblies(Assembly kernel, Path[] roots,
			LocalStore localStore, ModuleRepository moduleRepository){
		ModuleScanner scanner = new ModuleScanner(roots);
		return scanner.scanning("assembly.xml", new AssemblyXmlParser(kernel, localStore, moduleRepository));
	}
	
	/**
	 * 扫描的根目录
	 * @param localStore {@link LocalStore}
	 * @return {@link Path}数组.
	 */
	protected Path[] getRoots(LocalStore localStore) {
		return new Path[] {localStore.getDeploymentDirectory(null)};
	}
}
